//
//  YYPushTransitioningDelegate.m
//  YYTransitionAnimation
//
//  Created by 袁培超 on 2024/3/26.
//

#import "YYPushTransitioningDelegate.h"

@interface YYPushTransitioningDelegate () <UIViewControllerAnimatedTransitioning, UIGestureRecognizerDelegate>
@property(nonatomic,   weak) UIViewController *viewControllerToPresent;
@property(nonatomic, assign) BOOL isPresentAnimationing;
@property(nonatomic, assign) BOOL interacting;
@property(nonatomic, strong) UIPercentDrivenInteractiveTransition *interactivePopTransition;
@property(nonatomic, strong) UIView *backgroundView;
@property(nonatomic,   weak) UIView *shadowSuperView;
@end

@implementation YYPushTransitioningDelegate


- (void)configureTransition:(UIViewController *)viewControllerToPresent interacting:(BOOL)interacting
{
    self.viewControllerToPresent = viewControllerToPresent;
    if (viewControllerToPresent && interacting) {
        UIScreenEdgePanGestureRecognizer *gesture = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
        gesture.edges = UIRectEdgeLeft;
        [viewControllerToPresent.view addGestureRecognizer:gesture];
        
        if ([viewControllerToPresent isKindOfClass:[UINavigationController class]]) {
            UINavigationController *navc = ((UINavigationController*)self.viewControllerToPresent);
            navc.interactivePopGestureRecognizer.delegate = self;
            gesture.delegate = self;
        }
    }
}

//- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
//{
//    return YES;
//}

//- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
//{
//    return YES;
//}

- (void)handleGesture:(UIScreenEdgePanGestureRecognizer *)gesture
{
    UIViewController *formVC = self.viewControllerToPresent;
    CGFloat changeX = [gesture translationInView:formVC.view].x;
    CGFloat progress = changeX / formVC.view.bounds.size.width;
    CGFloat velocity = [gesture velocityInView:formVC.view].x;
    progress = fminf(1.0, fmaxf(0.0, progress));
    
    if (gesture.state == UIGestureRecognizerStateBegan) {
        self.interacting = YES;
        self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
        self.interactivePopTransition.completionCurve = UIViewAnimationCurveEaseInOut;
        [formVC dismissViewControllerAnimated:YES completion:NULL];
    }
    else if (gesture.state == UIGestureRecognizerStateChanged) {
        [self.interactivePopTransition updateInteractiveTransition:progress];
    }
    else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateCancelled) {
        self.interacting = NO;
        if (progress > 0.5) {
            self.interactivePopTransition.completionSpeed = 1 - progress;
            [self.interactivePopTransition finishInteractiveTransition];
        }
        else if (velocity > 800.0) {
            self.interactivePopTransition.completionSpeed = 1 - progress;
            [self.interactivePopTransition finishInteractiveTransition];
        }
        else {
            self.interactivePopTransition.completionSpeed = 1 - progress;
            [self.interactivePopTransition cancelInteractiveTransition];
        }
        self.interactivePopTransition = nil;
    }
}


- (void)addShadowToView:(UIView *)view
{
    self.shadowSuperView = view;
    view.layer.masksToBounds = NO;
    view.layer.shadowOffset = CGSizeMake(-1.0f, 0.0f);
    view.layer.shadowRadius = 5.0f;
    view.layer.shadowOpacity = 0.2f;
    view.layer.shouldRasterize = YES;
    view.layer.shadowPath = [UIBezierPath bezierPathWithRect:view.bounds].CGPath;
}

- (void)removeShadowToView:(UIView *)view
{
    view.layer.shadowOffset = CGSizeMake(0.0, -3.0);
    view.layer.shadowRadius = 3.0;
    view.layer.shadowOpacity = 0.0;
    view.layer.shouldRasterize = NO;
    view.layer.shadowPath = nil;
}

- (void)animateWithContext:(id<UIViewControllerContextTransitioning>)transitionContext
                 isPresent:(BOOL)isPresent
                animations:(void (^)(void))animations
                completion:(void (^ __nullable)(BOOL finished))completion
{
    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        if (isPresent) {
            self.backgroundView.alpha = 0.3f;
        }
        else {
            self.backgroundView.alpha = 0.0f;
        }
        if (animations) {
            animations();
        }
    } completion:^(BOOL finished) {
        [self.backgroundView removeFromSuperview];
        [self removeShadowToView:self.shadowSuperView];
        if (completion) {
            completion(finished);
        }
        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
    }];
}

#pragma mark - UIViewControllerTransitioningDelegate

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
                                                                  presentingController:(UIViewController *)presenting
                                                                      sourceController:(UIViewController *)source
{
    self.isPresentAnimationing = YES;
    return self;
}

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    self.isPresentAnimationing = NO;
    return self;
}

- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator
{
    return self.interacting ? self.interactivePopTransition : nil;
}

#pragma mark - UIViewControllerAnimatedTransitioning

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
    return 0.3f;
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController *toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    
    UIView* transView = nil;
    if (self.isPresentAnimationing) {
        transView = toViewController.view;
        [[transitionContext containerView] addSubview:toViewController.view];
//        [fromViewController.view addSubview:self.backgroundView];
    }else {
        transView = fromViewController.view;
        [transitionContext.containerView bringSubviewToFront:fromViewController.view];
//        [toViewController.view addSubview:self.backgroundView];
    }
//    self.backgroundView.frame = transView.frame;
    [self addShadowToView:transView];
//    NSLog(@"<-=-=-=-=> %@, %@",toViewController, fromViewController);
//    NSLog(@"<-=-=-=-=> %@, %@",[NSValue valueWithCGRect:toViewController.view.frame], [NSValue valueWithCGRect:fromViewController.view.frame]);
    CGFloat width   = transView.bounds.size.width;
    CGFloat height  = transView.bounds.size.height;
    transView.frame = CGRectMake(self.isPresentAnimationing ? width : 0, 0, width, height);
    CGRect toFrame  = CGRectMake(self.isPresentAnimationing ? 0 : width, 0, width, height);
        
    [self animateWithContext:transitionContext isPresent:self.isPresentAnimationing animations:^{
        transView.frame = toFrame;
    } completion:^(BOOL finished) {
        
    }];
}

#pragma mark - getter

- (UIView *)backgroundView {
    if (!_backgroundView) {
        _backgroundView = [[UIView alloc] init];
        _backgroundView.backgroundColor = [UIColor blackColor];
        _backgroundView.alpha = 0.f;
    }
    return _backgroundView;
}

@end
